
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   specific_test.py
@Time    :   2023/4/2 13:31:28
@Author  :   YangLiang
@Version :   1.0
@Contact :   YangLiang@chengtech.com
@License :   (C)Copyright 2022-2025
@Desc    :   None
'''

# here put the import lib
import binascii
import datetime
import time
from pytest_assume.plugin import assume
import sys
import os
import logging
# logging.getLogger().setLevel(logging.INFO)
import allure
import pytest

# curPath = os.path.abspath(os.path.dirname(__file__))
# rootPath = os.path.abspath(os.path.dirname(curPath) + os.path.sep + ".")
# sys.path.append(rootPath)
# sys.path.append(os.path.join(curPath,'commDriver'))
# sys.path.append(os.path.join(curPath,'data'))
# logging.info(sys.path)

from commDriver.TS_CAN import TSCAN, TSCAN_UDS,HIL_Obj
from commDriver.TS_CAN import TSMasterAPI
import Set_up
from commDriver.modbus_plc import *

sys.dont_write_bytecode = True
import Set_up

chn = 'CAN2'
dressing = 'UDSRRCR'
eras_write_info = {'eras_NVM_data':[0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00],  #执行擦除NVM数据的操作
            'eras_Calibrat_backupdata':[0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x00],  #执行擦除标定数据备份区域
            'eras_DID_backupdata':[0x33,0x33,0x33,0x00,0x00,0x00,0x00,0x00],  #执行擦除DID备份数据区域
            'write_all0_Calibratdata':[0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00],  #执行写入全0到标定数据的NVM blcok中
            'write_valid_Calibratdata':[0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00],  #执行写入有效的标定数据到NVM block中
            'write_all0_DIDdata':[0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00]   #执行写入全0到DID数据的NVM blcok中
}

eras_write_info_list = [('eras_NVM_data',[0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00]),  #执行擦除NVM数据的操作
            ('eras_Calibrat_backupdata',[0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x00]),  #执行擦除标定数据备份区域
            ('eras_DID_backupdata',[0x33,0x33,0x33,0x00,0x00,0x00,0x00,0x00]),  #执行擦除DID备份数据区域
            ('write_all0_Calibratdata',[0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00]),  #执行写入全0到标定数据的NVM blcok中
            ('write_valid_Calibratdata',[0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00]),  #执行写入有效的标定数据到NVM block中
            ('write_all0_DIDdata',[0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00])   #执行写入全0到DID数据的NVM blcok中
]

ALNData_eras_write_info = [
            ('eras_NVM_data',[0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00]),  #执行擦除NVM数据的操作
            ('eras_Calibrat_backupdata',[0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x00]),  #执行擦除标定数据备份区域
            ('write_all0_Calibratdata',[0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00]),  #执行写入全0到标定数据的NVM blcok中
            ('eras_DID_backupdata',[0x33,0x33,0x33,0x00,0x00,0x00,0x00,0x00]),  #执行擦除DID备份数据区域
            ('write_all0_DIDdata',[0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00])   #执行写入全0到DID数据的NVM blcok中

]

DIDData_eras_write_info = [
            # ('eras_NVM_data',[0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00]),  #执行擦除NVM数据的操作
            ('eras_DID_backupdata',[0x33,0x33,0x33,0x00,0x00,0x00,0x00,0x00]),  #执行擦除DID备份数据区域
            ('write_all0_DIDdata',[0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00])   #执行写入全0到DID数据的NVM blcok中
]

WriteDID = [([0x2E,0xF1,0x90,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfE],[0x6E,0xF1,0x90]),
            # ([0x2E,0xF1,0x84,0x22,0x09,0x30,0x00,0x00,0x00,0x00,0x00,0x01],[0x6E,0xF1,0x84]),
            ([0x2E,0x12,0x66,0x00,0x00,0x00,0x01],[0x6E,0x12,0x66]),
            ([0x2E,0x12,0x6A,0x00,0x01],[0x6E,0x12,0x6A]),
            ([0x2E,0x12,0x6B,0x00,0x01],[0x6E,0x12,0x6B]),
            ([0x2E,0x12,0x6C,0x00,0x01],[0x6E,0x12,0x6C])]

class Test_Databackup():

    def test_A_write_DID(self,Driver,iStep=1):
        seed = []
        with allure.step('step1:Request:0x27,0x01, # Response:0x67,0x01,0xXX,0xXX,0xXX,0xXX'):
            uds_rep,size = Driver['UDS'].req_and_res_can([0x10,0x03],2)
            uds_rep,size = Driver['UDS'].req_and_res_can([0x27,0x01],2)
            if  uds_rep[0:2] != [0x67,0x01]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ')  
                logging.error(f'correct response:[0x67,0x01], actual response:[{actuRespStr}]')
            with assume: assert (uds_rep[0:2] == [0x67,0x01] and size == 18)
        with allure.step('step2:Request:0x27,0x02, # Response:0x67,0x02'):
            seed = uds_rep[2:]
            key = Driver['CAN'].calcKey(seed)
            send_key = [0x27,0x02] + key
            uds_rep,size = Driver['UDS'].req_and_res_can(send_key,len(send_key))
            if  uds_rep[0:2] != [0x67,0x02]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ')  
                correct_send_key = binascii.b2a_hex(bytearray(send_key), ' ')  
                logging.error(f'correct response:[{correct_send_key}], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0:2] == [0x67,0x02]

            for req,resp in WriteDID:
                uds_rep,size = Driver['UDS'].req_and_res_can(req,len(req))
                with assume: assert size == len(resp)
                if size > 0:
                    if  uds_rep != resp:
                        actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                        cor_RespStr = binascii.b2a_hex(bytearray(resp), ' ') 
                        logging.error(f'correct response:{cor_RespStr}, actual response:[{actuRespStr}]')
                    for i in range(len(resp)):
                        with assume: assert uds_rep[i] == resp[i]
                else:
                    with assume: assert 1 == size
                    logging.error("no response,size = 0")
            iStep += 1
        return iStep

    def read_DID(self,Driver,iStep=1):
        uds_rep,size = Driver['UDS'].req_and_res_can([0x19,0x02,0x0B],3)
        uds_rep,size = Driver['UDS'].req_and_res_can([0x10,0x03],2)
        for req,resp in WriteDID:
            uds_rep,size = Driver['UDS'].req_and_res_can([0x22]+req[1:3],3)
            if  uds_rep[0] != 0x62:
                logging.error(f'correct response:{0x62}, actual response:[{hex(uds_rep[0])}]')
            if  uds_rep[3:] != req[3:]:
                    actuRespStr = binascii.b2a_hex(bytearray(uds_rep[3:]), ' ') 
                    cor_RespStr = binascii.b2a_hex(bytearray(req[3:]), ' ') 
                    logging.error(f'correct response:{cor_RespStr}, actual response:[{actuRespStr}]')
            with assume: assert (uds_rep[0] == 0x62 and uds_rep[3:] == req[3:])

            iStep += 1
        return iStep

        

    def erase_write_data(self,Driver,eras_write_date,iStep):
        with allure.step(f"Step{iStep}:故障注入接口,等待5s"):
            
            Driver[chn].send_Frame(0x157,eras_write_date,'CAN')
            time.sleep(5)
            logging.info(f'发送1次故障注入帧  {eras_write_date}  后已等5s')
            iStep += 1
        return iStep


    def check_Calibrat_DTC(self,Driver,flag_old,flag_now,iStep):
        with allure.step(f"Step{iStep}:检查是否有标定的DTC"):
            logging.info('检查是否有标定的DTC')
            a,b,c = Driver[dressing].search_DTC([0x19,0x02,0x0B],[0x98,0x7C,0x54,0x08],1)
            with assume:assert a == flag_old
            a,b,c = Driver[dressing].search_DTC([0x19,0x02,0x0B],[0x98,0x7C,0x54,0x09],2)
            with assume:assert a == flag_now
            uds_rep,size = Driver['UDS'].req_and_res_can([0x14,0xFF,0xFF,0xFF],4)
            time.sleep(0.5)
            iStep += 1
        return iStep


    def check_sleep(self,Driver,iStep):
        with allure.step(f"Step{iStep}:进入休眠"):
            
            Driver['CAN'].wakeup_ctrl(False)
            time.sleep(2)
            Driver['CAN'].vechile_message(Driver,False)
            
            sleepmode = False
            start_time = time.time()
            while( (time.time()-start_time) < 10):
                Radar_APP_message_fsp = Driver['CAN'].get_fps(0x385,'CANFD')  # app CAN1
                v,i =Driver['power'].Read_Measure()
                # sleepmode = True if ( i < 0.08) else False   #开机fsp返回-1
                sleepmode = True if ((Radar_APP_message_fsp == 0 or Radar_APP_message_fsp == -1)) else False   #开机fsp返回-1
                if sleepmode:
                    break
            
            time.sleep(2)
            iStep += 1

        return iStep

    def check_wakeup(self,Driver,iStep):
        with allure.step(f"Step{iStep}:唤醒雷达"):
            
            Driver['CAN'].vechile_message(Driver,True)
            time.sleep(2)
            Driver['CAN'].wakeup_ctrl(True)
            logging.info('发唤醒帧,钥匙信号为on,发车身报文')
            iStep += 1

        return iStep



    ids = ["Request:{0}".format(send_info) for send_info,send_data in ALNData_eras_write_info]
    @pytest.mark.repeat(1)
    @pytest.mark.parametrize('send_info,send_data', ALNData_eras_write_info,ids=ids)
    def test_ALNData_eras_NVM_date_sleep(self,action,Driver,send_info,send_data):
        # 存在有效标定数据和备份数据时，擦除nvm数据，等待5s断电（休眠），再上电，等待10s，不报标定故障，走休眠过程
        # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
        iStep = 1
        # logging.info('delay 5s')
        # time.sleep(5)
        iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
        # iStep = self.check_sleep(Driver,iStep)
        # iStep = self.check_wakeup(Driver,iStep)
        iStep = self.read_DID(Driver,iStep=1)

        logging.info('eras date start')
        iStep = self.erase_write_data(Driver,send_data,iStep)
        
        iStep = self.check_sleep(Driver,iStep)
        iStep = self.check_wakeup(Driver,iStep)
        logging.info('delay 10s')
        time.sleep(10)
        iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
        iStep = self.read_DID(Driver,iStep=1)

    # def test_ALNData_eras_Calibrat_backup_data_sleep(self,action,Driver):
    #     # 存在有效标定数据和备份数据时，擦除备份数据，等待5s断电，再上电，等待10s，不报标定故障，走休眠过程    (重复测试)
    #     # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
    #     iStep = 1
    #     logging.info('delay 5s')
    #     time.sleep(5)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
    #     iStep = self.check_sleep(Driver,iStep)
    #     iStep = self.check_wakeup(Driver,iStep)

    #     logging.info('eras date start')
    #     iStep = self.erase_write_data(Driver,eras_write_info['eras_Calibrat_backupdata'],iStep)
        
    #     iStep = self.check_sleep(Driver,iStep)
    #     iStep = self.check_wakeup(Driver,iStep)
    #     logging.info('delay 10s')
    #     time.sleep(10)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)

    # def test_ALNData_write_all0_data_sleep(self,action,Driver):
    #     # 存在有效标定数据和备份数据时，将全0数据写入标定的nvm中，等待5s断电，再上电，等待10s，不报标定故障，走休眠过程
    #     # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
    #     iStep = 1
    #     logging.info('delay 5s')
    #     time.sleep(5)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
    #     iStep = self.check_sleep(Driver,iStep)
    #     iStep = self.check_wakeup(Driver,iStep)

    #     logging.info('eras date start')
    #     iStep = self.erase_write_data(Driver,eras_write_info['write_all0_Calibratdata'],iStep)
        
    #     iStep = self.check_sleep(Driver,iStep)
    #     iStep = self.check_wakeup(Driver,iStep)
    #     logging.info('delay 10s')
    #     time.sleep(10)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)



    ids = ["Request:{0}".format(send_info) for send_info,send_data in ALNData_eras_write_info]
    @pytest.mark.repeat(1)
    @pytest.mark.parametrize('send_info,send_data', ALNData_eras_write_info,ids=ids)
    def test_ALNData_eras_NVM_date_reset(self,action,Driver,send_info,send_data):
        # 存在有效标定数据和备份数据时，擦除nvm数据，等待5s断电（休眠），再上电，等待10s，不报标定故障，走休眠过程
        # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
        iStep = 1
        # logging.info('delay 5s')
        # time.sleep(5)
        iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
        # iStep = self.check_sleep(Driver,iStep)
        # iStep = self.check_wakeup(Driver,iStep)
        iStep = self.read_DID(Driver,iStep=1)
        time.sleep(1)

        logging.info('eras date start')
        iStep = self.erase_write_data(Driver,send_data,iStep)
        
        uds_rep,size = Driver['UDS'].req_and_res_can([0x11,0x01],2)
        logging.info('delay 10s')
        time.sleep(10)
        iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
        iStep = self.read_DID(Driver,iStep=1)

    # def test_ALNData_eras_Calibrat_backup_data_reset(self,action,Driver):
    #     # 存在有效标定数据和备份数据时，擦除备份数据，等待5s断电，再上电，等待10s，不报标定故障，走休眠过程    (重复测试)
    #     # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
    #     iStep = 1
    #     logging.info('delay 5s')
    #     time.sleep(5)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
    #     iStep = self.check_sleep(Driver,iStep)
    #     iStep = self.check_wakeup(Driver,iStep)

    #     logging.info('eras date start')
    #     iStep = self.erase_write_data(Driver,eras_write_info['eras_Calibrat_backupdata'],iStep)
        
    #     iStep = Driver['CAN'].restartMRR_11(Driver, iStep)
    #     logging.info('delay 10s')
    #     time.sleep(10)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)

    # def test_ALNData_write_all0_data_reset(self,action,Driver):
    #     # 存在有效标定数据和备份数据时，将全0数据写入标定的nvm中，等待5s断电，再上电，等待10s，不报标定故障，走休眠过程
    #     # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
    #     iStep = 1
    #     logging.info('delay 5s')
    #     time.sleep(5)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
    #     iStep = self.check_sleep(Driver,iStep)
    #     iStep = self.check_wakeup(Driver,iStep)

    #     logging.info('eras date start')
    #     iStep = self.erase_write_data(Driver,eras_write_info['write_all0_Calibratdata'],iStep)
        
    #     iStep = Driver['CAN'].restartMRR_11(Driver, iStep)
    #     logging.info('delay 10s')
    #     time.sleep(10)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)



    ids = ["Request:{0}".format(send_info) for send_info,send_data in ALNData_eras_write_info]
    @pytest.mark.repeat(1)
    @pytest.mark.parametrize('send_info,send_data', ALNData_eras_write_info,ids=ids)    
    def test_ALNData_eras_NVM_date_poweroff(self,action,Driver,send_info,send_data, power_reset):
        # 存在有效标定数据和备份数据时，擦除nvm数据，等待5s断电（休眠），再上电，等待10s，不报标定故障，走休眠过程
        # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
        iStep = 1
        # logging.info('delay 5s')
        # time.sleep(5)
        iStep = self.check_Calibrat_DTC(Driver,False,True,iStep)
        # iStep = self.check_sleep(Driver,iStep)
        # iStep = self.check_wakeup(Driver,iStep)
        iStep = self.read_DID(Driver,iStep=1)

        logging.info('eras date start')
        iStep = self.erase_write_data(Driver,send_data,iStep)
        
        iStep = Driver['CAN'].restartMRR_Power(Driver, iStep)
        logging.info('delay 10s')
        time.sleep(10)
        iStep = self.check_Calibrat_DTC(Driver,False,True,iStep)
        iStep = self.read_DID(Driver,iStep=1)

    # def test_ALNData_eras_Calibrat_backup_data_poweroff(self,action,Driver):
    #     # 存在有效标定数据和备份数据时，擦除备份数据，等待5s断电，再上电，等待10s，不报标定故障，走休眠过程    (重复测试)
    #     # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
    #     iStep = 1
    #     logging.info('delay 5s')
    #     time.sleep(5)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
    #     iStep = self.check_sleep(Driver,iStep)
    #     iStep = self.check_wakeup(Driver,iStep)

    #     logging.info('eras date start')
    #     iStep = self.erase_write_data(Driver,eras_write_info['eras_Calibrat_backupdata'],iStep)
        
    #     iStep = Driver['CAN'].restartMRR_Power(Driver, iStep)
    #     logging.info('delay 10s')
    #     time.sleep(10)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)

    # def test_ALNData_write_all0_data_poweroff(self,action,Driver):
    #     # 存在有效标定数据和备份数据时，将全0数据写入标定的nvm中，等待5s断电，再上电，等待10s，不报标定故障，走休眠过程
    #     # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
    #     iStep = 1
    #     logging.info('delay 5s')
    #     time.sleep(5)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
    #     iStep = self.check_sleep(Driver,iStep)
    #     iStep = self.check_wakeup(Driver,iStep)

    #     logging.info('eras date start')
    #     iStep = self.erase_write_data(Driver,eras_write_info['write_all0_Calibratdata'],iStep)
        
    #     iStep = Driver['CAN'].restartMRR_Power(Driver, iStep)
    #     logging.info('delay 10s')
    #     time.sleep(10)
    #     iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)



    ids = ["Request:{0}".format(send_info) for send_info,send_data in DIDData_eras_write_info]
    @pytest.mark.repeat(1)
    @pytest.mark.parametrize('send_info,send_data', DIDData_eras_write_info,ids=ids) 
    def DIDData_eras_DID_backup_data_sleep(self,action,Driver,send_info,send_data):
        # 存在有效标定数据和备份数据时，擦除nvm数据，等待5s断电（休眠），再上电，等待10s，不报标定故障，走休眠过程
        # 备注：如果本点火周期未报标定故障，走休眠过程会将数据同时存储在nvm和备份区
        iStep = 1
        logging.info('delay 5s')
        time.sleep(5)
        iStep = self.check_Calibrat_DTC(Driver,False,False,iStep)
        iStep = self.check_sleep(Driver,iStep)
        iStep = self.check_wakeup(Driver,iStep)
        iStep = self.read_DID(Driver,iStep=1)

        logging.info('eras date start')
        iStep = self.erase_write_data(Driver,send_data,iStep)
        
        iStep = self.check_sleep(Driver,iStep)
        iStep = self.check_wakeup(Driver,iStep)
        logging.info('delay 10s')
        time.sleep(10)
        iStep = self.read_DID(Driver,iStep=1)